#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>

#define WIDTH 20
#define HEIGHT 20
#define MAX_SNAKE_LENGTH 100

#define BORDER_COLOR 7
#define FOOD_COLOR 4
#define SNAKE_COLOR 2
#define DEFAULT_COLOR 15


typedef struct {
    int x;
    int y;
} Point;


Point snake[MAX_SNAKE_LENGTH];  
int snakeLength = 1;            
Point food;                     
int direction = 0;              

// filepath: a:\code_doc\code_c\1\main.c
// ...existing code...
void gotoxy(int x, int y) {
    COORD pos;
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
// ...existing code...

void setColor(int color) {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}

void drawBoard() {
    gotoxy(0, 0);

    setColor(BORDER_COLOR);
    for (int i = 0; i < WIDTH + 2; i++)
        printf("█"); // 用实心方块美化墙体
    setColor(DEFAULT_COLOR);
    printf("\n");

    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            if (x == 0) {
                setColor(BORDER_COLOR);
                printf("█");
                setColor(DEFAULT_COLOR);
            }

            if (x == food.x && y == food.y) {
                setColor(FOOD_COLOR);
                printf("x");
                setColor(DEFAULT_COLOR);
            } else {
                int snakePart = 0;
                for (int i = 0; i < snakeLength; i++) {
                    if (snake[i].x == x && snake[i].y == y) {
                        snakePart = 1;
                        break;
                    }
                }
                if (snakePart) {
                    setColor(SNAKE_COLOR);
                    printf("o");
                    setColor(DEFAULT_COLOR);
                } else {
                    printf(" ");
                }
            }

            if (x == WIDTH - 1) {
                setColor(BORDER_COLOR);
                printf("█");
                setColor(DEFAULT_COLOR);
            }
        }
        printf("\n");
    }

    setColor(BORDER_COLOR);
    for (int i = 0; i < WIDTH + 2; i++)
        printf("█");
    setColor(DEFAULT_COLOR);
    printf("\n");
}


void moveSnake() {
    Point prev = snake[0];
    Point prev2;


    switch (direction) {
        case 0: 
            snake[0].y--;
            break;
        case 1:  
            snake[0].x++;
            break;
        case 2: 
            snake[0].y++;
            break;
        case 3:  
            snake[0].x--;
            break;
    }

    for (int i = 1; i < snakeLength; i++) {
        prev2 = snake[i];
        snake[i] = prev;
        prev = prev2;
    }
}


int checkCollision() {
    
    if (snake[0].x < 0 || snake[0].x >= WIDTH || snake[0].y < 0 || snake[0].y >= HEIGHT)
        return 1;
    // 检查蛇头是否与身体其他部分相撞
    // 从第二个体节开始检查，因为第一个体节是蛇头   
    for (int i = 1; i < snakeLength; i++) {
        if (snake[0].x == snake[i].x && snake[0].y == snake[i].y)
            return 1;
    }

    return 0;
}

void generateFood() {
    food.x = rand() % WIDTH;
    food.y = rand() % HEIGHT;
}


int checkFood() {
    if (snake[0].x == food.x && snake[0].y == food.y) {
        snake[snakeLength] = snake[snakeLength - 1]; //初始化新增体节位置
        snakeLength++;
        generateFood();
        return 1;
    }
    return 0;
}


void input() {
    if (_kbhit()) {
        switch (_getch()) {
            case 'w':  
                if (direction != 2) direction = 0;
                break;
            case 'd':  // 上
        
                if (direction != 3) direction = 1;
                break;
            case 's':  // 下
                if (direction != 0) direction = 2;
                break;
            case 'a':  // 左
                if (direction != 1) direction = 3;
                break;
            case 'q':  // 右
                exit(0);
            case 27:   // ESC 键
                exit(0);
        }
    }
}

void saveScore(int score) {
    // 保存本次得分
    FILE *fp = fopen("score.txt", "w");
    if (fp) {
        fprintf(fp, "%d\n", score);
        fclose(fp);
    }
}

int loadHighScore() {
    int high = 0;
    FILE *fp = fopen("highscore.txt", "r");
    if (fp) {
        fscanf(fp, "%d", &high);
        fclose(fp);
    }
    return high;
}

void saveHighScore(int score) {
    FILE *fp = fopen("highscore.txt", "w");
    if (fp) {
        fprintf(fp, "%d\n", score);
        fclose(fp);
    }
}

void showGameOverScreen() {
    int score = snakeLength - 1;
    int high = loadHighScore();
    saveScore(score);
    if (score > high) {
        saveHighScore(score);
        high = score;
    }

    system("cls");
    setColor(FOOD_COLOR);
    printf("\n\n");
    printf("  ██████   █████  ███    ███ ███████     ███████ ██    ██ ███████ ██████  \n");
    printf(" ██       ██   ██ ████  ████ ██          ██   ██ ██    ██ ██      ██   ██ \n");
    printf(" ██   ███ ███████ ██ ████ ██ █████       ██   ██ ██    ██ █████   ██████  \n");
    printf(" ██    ██ ██   ██ ██  ██  ██ ██          ██   ██ ██    ██ ██      ██   ██ \n");
    printf("  ██████  ██   ██ ██      ██ ███████     ███████  ██████  ███████ ██   ██ \n");
    printf("\n");
    setColor(DEFAULT_COLOR);
    printf("             游戏结束！\n");
    printf("             得分：%d\n", score);
    printf("             最高分：%d\n", high);
    printf("\n        按任意键退出...\n");
    _getch();
}

int selectSpeed() {
    int choice = 0;
    while (1) {

        setColor(DEFAULT_COLOR);
        printf("\n");
        printf("         ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");
        printf("         ┃         贪吃蛇小游戏         ┃\n");
        printf("         ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n");
        printf("         ┃ 请选择游戏速度：             ┃\n");
        printf("         ┃                              ┃\n");
        printf("         ┃   1. 慢速（300ms/步）        ┃\n");
        printf("         ┃   2. 中速（150ms/步）        ┃\n");
        printf("         ┃   3. 快速（75ms/步）         ┃\n");
        printf("         ┃                              ┃\n");
        printf("         ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n");
        printf("\n         请输入数字 1-3 并回车：");

        scanf("%d", &choice);
        if (choice >= 1 && choice <= 3) break;
    }
    switch (choice) {
        case 1: return 300;
        case 2: return 150;
        case 3: return 75;
        default: return 150;
    }
}

int main() {
    SetConsoleOutputCP(65001);
    // 隐藏光标
    CONSOLE_CURSOR_INFO cursor_info = {1, 0};
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);//隐藏光标（关闭光标闪烁）

    int sp = selectSpeed(); // 获取速度设置
    // 
    snake[0].x = WIDTH / 2;
    snake[0].y = HEIGHT / 2;

    generateFood();

    system("cls"); //清除速度设定页面

    while (1) {
        drawBoard();
        input();
        moveSnake();

        if (checkCollision()) {
            showGameOverScreen();
            break;
        }

        if (checkFood()) {
            //

        }

        Sleep(sp);//
    }

    system("pause");
    return 0;
}
